const cheerio = require('cheerio');

// 示例 HTML - 模拟一个电商页面的商品列表
const html = `
<!DOCTYPE html>
<html>
<head>
    <title>商品列表</title>
</head>
<body>
    <div class="container">
        <h1 id="page-title">热门商品推荐</h1>
        <div class="product-list">
            <div class="product-item" data-id="1001">
                <img src="/images/iphone15.jpg" alt="iPhone 15">
                <h3 class="product-name">Apple iPhone 15 Pro</h3>
                <p class="product-desc">6.1英寸屏幕，A17 Pro芯片</p>
                <div class="price-info">
                    <span class="original-price">原价：¥8999</span>
                    <span class="current-price">现价：¥7999</span>
                    <span class="discount">-11%</span>
                </div>
                <div class="rating">
                    <span class="stars">★★★★★</span>
                    <span class="review-count">2580条评价</span>
                </div>
                <div class="stock">库存：<em>15</em>件</div>
            </div>
            
            <div class="product-item" data-id="1002">
                <img src="/images/macbook.jpg" alt="MacBook Pro">
                <h3 class="product-name">MacBook Pro 14寸</h3>
                <p class="product-desc">M3 Pro芯片，18GB内存</p>
                <div class="price-info">
                    <span class="original-price">原价：¥16999</span>
                    <span class="current-price">现价：¥15999</span>
                    <span class="discount">-6%</span>
                </div>
                <div class="rating">
                    <span class="stars">★★★★☆</span>
                    <span class="review-count">856条评价</span>
                </div>
                <div class="stock">库存：<em>8</em>件</div>
            </div>
            
            <div class="product-item" data-id="1003">
                <img src="/images/airpods.jpg" alt="AirPods">
                <h3 class="product-name">AirPods Pro 2</h3>
                <p class="product-desc">主动降噪，空间音频</p>
                <div class="price-info">
                    <span class="original-price">原价：¥1999</span>
                    <span class="current-price">现价：¥1799</span>
                    <span class="discount">-10%</span>
                </div>
                <div class="rating">
                    <span class="stars">★★★★★</span>
                    <span class="review-count">5832条评价</span>
                </div>
                <div class="stock">库存：<em>0</em>件</div>
            </div>
        </div>
    </div>
</body>
</html>
`;

console.log('='.repeat(60));
console.log('三种网页解析方法对比示例');
console.log('='.repeat(60));

// ===========================
// 方法一：CSS选择器（使用Cheerio）
// ===========================
console.log('\n【方法一：CSS选择器解析】\n');

const $ = cheerio.load(html);

// 1. 获取页面标题
const pageTitle = $('#page-title').text();
console.log('页面标题:', pageTitle);

// 2. 获取所有商品信息
console.log('\n商品列表:');
$('.product-item').each((index, element) => {
    const $item = $(element);

    const product = {
        id: $item.attr('data-id'),
        name: $item.find('.product-name').text(),
        description: $item.find('.product-desc').text(),
        originalPrice: $item.find('.original-price').text(),
        currentPrice: $item.find('.current-price').text(),
        discount: $item.find('.discount').text(),
        rating: $item.find('.stars').text().length, // 星星数量
        reviewCount: $item.find('.review-count').text(),
        stock: $item.find('.stock em').text(),
        image: $item.find('img').attr('src')
    };

    console.log(`\n商品 ${index + 1}:`, product);
});

// 3. 查找特定条件的商品
console.log('\n有货商品:');
$('.product-item').filter((i, el) => {
    const stock = parseInt($(el).find('.stock em').text());
    return stock > 0;
}).each((i, el) => {
    console.log('- ' + $(el).find('.product-name').text());
});

// ===========================
// 方法二：使用Cheerio的XPath式选择
// ===========================
console.log('\n' + '='.repeat(60));
console.log('\n【方法二：类XPath选择（使用Cheerio高级选择器）】\n');

// 注意：由于xpath库的兼容性问题，我们使用Cheerio的高级选择器来模拟XPath功能

// 1. 获取页面标题 (模拟 //h1[@id="page-title"])
const title = $('h1[id="page-title"]').text();
console.log('页面标题:', title);

// 2. 获取所有商品名称 (模拟 //h3[@class="product-name"])
console.log('\n所有商品名称:');
$('h3[class="product-name"]').each((index, el) => {
    console.log(`${index + 1}. ${$(el).text()}`);
});

// 3. 获取价格信息 (模拟复杂的XPath路径)
console.log('\n价格信息:');
$('div[class="product-item"]').each((index, item) => {
    const $item = $(item);
    const name = $item.find('h3[class="product-name"]').text();
    const currentPrice = $item.find('span[class="current-price"]').text();
    const discount = $item.find('span[class="discount"]').text();
    console.log(`${name}: ${currentPrice} (${discount})`);
});

// 4. 查找评价超过1000条的商品 (模拟XPath条件)
console.log('\n热门商品（评价>1000）:');
$('.product-item').each((index, item) => {
    const $item = $(item);
    const reviewText = $item.find('.review-count').text();
    const reviewCount = parseInt(reviewText.match(/\d+/)[0]);
    if (reviewCount > 1000) {
        const name = $item.find('.product-name').text();
        console.log(`- ${name}: ${reviewText}`);
    }
});

// 5. 查找库存为0的商品 (模拟 //div[@class="product-item"][.//em[text()="0"]])
console.log('\n库存为0的商品:');
$('.product-item').filter((i, el) => {
    return $(el).find('.stock em').text() === '0';
}).each((i, el) => {
    console.log('- ' + $(el).find('.product-name').text());
});

// 6. 使用更复杂的选择器
console.log('\n使用复杂选择器查找折扣大于10%的商品:');
$('.product-item').filter((i, el) => {
    const discountText = $(el).find('.discount').text();
    const discountValue = parseInt(discountText.replace(/[^\d]/g, ''));
    return discountValue >= 10;
}).each((i, el) => {
    const name = $(el).find('.product-name').text();
    const discount = $(el).find('.discount').text();
    console.log(`- ${name}: ${discount}`);
});

// ===========================
// 方法三：正则表达式解析
// ===========================
console.log('\n' + '='.repeat(60));
console.log('\n【方法三：正则表达式解析】\n');

// 1. 提取页面标题
const titleRegex = /<h1[^>]*id="page-title"[^>]*>([^<]+)<\/h1>/;
const titleMatch = html.match(titleRegex);
console.log('页面标题:', titleMatch ? titleMatch[1] : '未找到');

// 2. 提取所有商品名称
console.log('\n所有商品名称:');
const nameRegex = /<h3\s+class="product-name">([^<]+)<\/h3>/g;
let nameMatch;
let productIndex = 1;
while ((nameMatch = nameRegex.exec(html)) !== null) {
    console.log(`${productIndex++}. ${nameMatch[1]}`);
}

// 3. 提取价格信息（更复杂的正则）
console.log('\n价格信息:');
// 使用正则提取每个商品块
const productRegex = /<div\s+class="product-item"[^>]*>([\s\S]*?)(?=<div\s+class="product-item"|<\/div>\s*<\/div>)/g;
let productMatch;
while ((productMatch = productRegex.exec(html)) !== null) {
    const productHtml = productMatch[1];

    // 从商品块中提取信息
    const name = productHtml.match(/<h3\s+class="product-name">([^<]+)<\/h3>/);
    const originalPrice = productHtml.match(/<span\s+class="original-price">([^<]+)<\/span>/);
    const currentPrice = productHtml.match(/<span\s+class="current-price">([^<]+)<\/span>/);
    const discount = productHtml.match(/<span\s+class="discount">([^<]+)<\/span>/);

    if (name && currentPrice) {
        console.log(`\n商品: ${name[1]}`);
        console.log(`  ${originalPrice ? originalPrice[1] : ''}`);
        console.log(`  ${currentPrice[1]}`);
        console.log(`  折扣: ${discount ? discount[1] : ''}`);
    }
}

// 4. 提取所有数字类信息
console.log('\n\n数字信息提取:');
// 提取所有价格
const priceRegex = /¥(\d+)/g;
const prices = [];
let priceMatch;
while ((priceMatch = priceRegex.exec(html)) !== null) {
    prices.push(parseInt(priceMatch[1]));
}
console.log('所有价格:', prices);

// 提取评价数量
const reviewRegex = /(\d+)条评价/g;
const reviews = [];
let reviewMatch;
while ((reviewMatch = reviewRegex.exec(html)) !== null) {
    reviews.push({
        count: parseInt(reviewMatch[1]),
        text: reviewMatch[0]
    });
}
console.log('\n评价统计:', reviews);

// 提取库存数量
const stockRegex = /库存：<em>(\d+)<\/em>件/g;
const stocks = [];
let stockMatch;
while ((stockMatch = stockRegex.exec(html)) !== null) {
    stocks.push(parseInt(stockMatch[1]));
}
console.log('\n库存数量:', stocks);

// 5. 组合多个正则提取完整商品信息
console.log('\n\n使用正则提取完整商品信息:');
// 重置正则的lastIndex
productRegex.lastIndex = 0;

const products = [];
while ((productMatch = productRegex.exec(html)) !== null) {
    const productHtml = productMatch[0];

    // 提取各个字段
    const idMatch = productHtml.match(/data-id="(\d+)"/);
    const nameMatch = productHtml.match(/<h3\s+class="product-name">([^<]+)<\/h3>/);
    const currentPriceMatch = productHtml.match(/现价：¥(\d+)/);
    const stockMatch = productHtml.match(/库存：<em>(\d+)<\/em>/);
    const reviewMatch = productHtml.match(/(\d+)条评价/);

    if (nameMatch) {
        products.push({
            id: idMatch ? idMatch[1] : '',
            name: nameMatch[1],
            price: currentPriceMatch ? parseInt(currentPriceMatch[1]) : 0,
            stock: stockMatch ? parseInt(stockMatch[1]) : 0,
            reviews: reviewMatch ? parseInt(reviewMatch[1]) : 0
        });
    }
}

console.log('解析结果:', products);

// ===========================
// 总结对比
// ===========================
console.log('\n' + '='.repeat(60));
console.log('\n【三种方法对比总结】\n');

console.log('1. CSS选择器（Cheerio）:');
console.log('   ✅ 优点: 语法简单直观，类似jQuery，易于学习');
console.log('   ✅ 适合: 标准的HTML结构，有明确的class和id');
console.log('   ❌ 缺点: 对于复杂的条件筛选不够灵活');

console.log('\n2. 高级选择器（类XPath功能）:');
console.log('   ✅ 优点: 可以实现类似XPath的复杂选择');
console.log('   ✅ 适合: 需要条件筛选和复杂路径的场景');
console.log('   ❌ 缺点: 需要结合JavaScript代码实现复杂逻辑');

console.log('\n3. 正则表达式:');
console.log('   ✅ 优点: 不依赖DOM解析库，适合提取特定格式文本');
console.log('   ✅ 适合: 简单的文本提取，特定格式的数据');
console.log('   ❌ 缺点: 维护困难，容易出错，不适合复杂HTML');

console.log('\n建议: 优先使用CSS选择器，复杂场景用高级选择器，文本提取用正则');

// ===========================
// 实用技巧展示
// ===========================
console.log('\n' + '='.repeat(60));
console.log('\n【实用技巧】\n');

// 1. 处理相对URL
console.log('1. 处理图片URL:');
$('.product-item img').each((i, el) => {
    const src = $(el).attr('src');
    const fullUrl = 'https://example.com' + src;
    console.log(`   原始: ${src} -> 完整: ${fullUrl}`);
});

// 2. 提取并清理文本
console.log('\n2. 清理价格文本:');
$('.current-price').each((i, el) => {
    const rawPrice = $(el).text();
    const cleanPrice = rawPrice.replace(/[^\d]/g, '');
    const priceNumber = parseInt(cleanPrice);
    console.log(`   原始: "${rawPrice}" -> 清理后: ${priceNumber}`);
});

// 3. 批量提取数据到数组
console.log('\n3. 批量提取到数组:');
const allPrices = $('.current-price').map((i, el) => {
    return parseInt($(el).text().replace(/[^\d]/g, ''));
}).get();
console.log('   所有价格:', allPrices);
console.log('   平均价格:', (allPrices.reduce((a, b) => a + b, 0) / allPrices.length).toFixed(0));